﻿using Engine;
using Game;

namespace Mekiasm
{
    public class MekRecipe
    {
        public string[] ingredians;
        public string[] fuelIngredians;
        public ComponentEnergyMachine.FuelType[] fuelIngredianTypes;
        public int[] fuelIngrediansAmount;
        public int[] Results;
        public int[] ResultCounts;
        public int[] FuelResults;
        public ComponentEnergyMachine.FuelType[] FuelResultTypes;
        public int[] FuelAmountResults;
        public int[] Remains;
        public int[] RemainCounts;
        private float requireHeatLevel;
        private float requirePlayerLevel;
        public string Message;
        private Point2 craftSize;
        public string craftName;
        public string description;
        private bool[] CraftChecks;
        private bool[] FuelCraftChecks;
        public float CraftSpeedFator;
        private int CraftMode = 0;

        public MekRecipe(int m_craftSize = 3, int m_fuelCraftSize = 0, int resultSize = 1, int remainSize = 0, int fuelResultSize = 0)
        {
            CraftSpeedFator = 1f;
            craftSize = new Point2(m_craftSize);            
            ingredians = new string[m_craftSize * m_craftSize];
            fuelIngredians = new string[m_fuelCraftSize * m_fuelCraftSize];
            fuelIngrediansAmount = new int[fuelIngredians.Length];
            fuelIngredianTypes = new ComponentEnergyMachine.FuelType[fuelIngredians.Length];
            Results = new int[resultSize];
            ResultCounts = new int[resultSize];
            FuelResults = new int[fuelResultSize];
            FuelResultTypes = new ComponentEnergyMachine.FuelType[fuelResultSize];
            FuelAmountResults = new int[fuelResultSize];
            Remains = new int[remainSize];
            RemainCounts = new int[remainSize];
            CraftChecks = new bool[ingredians.Length];
            FuelCraftChecks = new bool[fuelIngredians.Length];
            requirePlayerLevel = 1;
        }

        public MekRecipe SetCraftMode(int mode) { CraftMode = mode;return this; }

        public float GetSpeedFator() { return CraftSpeedFator; }

        public MekRecipe SetSpeedFator(float fator) { CraftSpeedFator = fator;return this; }

        public override string ToString()
        {
            return craftName;
        }

        public MekRecipe SetName(string name)
        {
            craftName = name;
            return this;
        }

        public MekRecipe SetDescriction(string desc)
        {
            description = desc;
            return this;

        }
        public MekRecipe SetRequirePlayerLevel(float l) { requirePlayerLevel = l;return this; }

        public MekRecipe SetRequireHeatLevel(float l) { requireHeatLevel = l; return this; }

        public string GetIngredian(int position, bool fuel = false)
        {
            return fuel ? fuelIngredians[position] : ingredians[position];
        }

        public MekRecipe SetIngredian(int position, string craftId, int fuelAmount = 0, bool fuel = false, ComponentEnergyMachine.FuelType fuelType = default)
        {
            if (fuel)
            {
                if (position >= fuelIngredians.Length) throw new System.Exception("无效的配方位置");
                fuelIngredians[position] = craftId;
                fuelIngredianTypes[position] = fuelType;
                fuelIngrediansAmount[position] = fuelAmount;
                FuelCraftChecks[position] = true;
            }
            else
            {
                if (position >= ingredians.Length) throw new System.Exception("无效的配方位置");
                ingredians[position] = craftId;
                CraftChecks[position] = true;
            }
            return this;
        }

        public MekRecipe SetRemainNeedCheck(bool fuel = false)
        {
            if (fuel)
            {
                for (int i = 0; i < FuelCraftChecks.Length; i++) FuelCraftChecks[i] = true;
            }
            else
            {
                for (int i = 0; i < CraftChecks.Length; i++) CraftChecks[i] = true;
            }
            return this;
        }

        public MekRecipe SetRemain(int position, int value, int fuelAmount = 1, bool fuel = false)
        {
            if (fuel)
            {
                if (position >= FuelResults.Length) throw new System.Exception("无效的保留结果位置");
                Remains[position] = value;
            }
            else
            {
                if (position >= Results.Length) throw new System.Exception("无效的保留结果位置");
                Remains[position] = value;
                RemainCounts[position] = fuelAmount;
            }
            return this;
        }

        public MekRecipe SetResult(int position, int value, int fuelAmount = 1, bool fuel = false, ComponentEnergyMachine.FuelType fuelType = default)
        {
            if (fuel)
            {
                if (position >= FuelResults.Length) throw new System.Exception("无效的合成结果位置");
                FuelResults[position] = value;
                FuelResultTypes[position] = fuelType;
                FuelAmountResults[position] = fuelAmount;
            }
            else
            {
                if (position >= Results.Length) throw new System.Exception("无效的合成结果位置");
                Results[position] = value;
                ResultCounts[position] = fuelAmount;
            }
            return this;
        }
        /// <summary>
        /// 配方匹配
        /// </summary>
        /// <param name="ingredians"></param>
        /// <param name="fuelIngredians"></param>
        /// <param name="ResultValues"></param>
        /// <param name="ResultFuelValues"></param>
        /// <param name="playerLevel"></param>
        /// <param name="heatLeval"></param>
        /// <returns></returns>
        public bool Match(string[] m_ingredians, string[] m_fuelIngredians, ComponentEnergyMachine.FuelType[] m_fuelIngredianTypes, long[] m_fuelIngredianAmount, ComponentEnergyMachine machine, float heatLevel, ComponentPlayer player)
        {
            if (machine.CraftModeType != CraftMode) return false;
            var craft = machine.CraftDevice;
            int i = 0;
            //结果位的物品是否和配方一致
            if (Results.Length > 0)
            {
                for (; i < craft.ResultSlotIndies.Length; i++)
                {
                    if (!machine.AquireItems(craft.ResultSlotIndies[i], Results[i], ResultCounts[i])) return false;
                }
            }
            //保留位的物品是否和配方一致
            if (Remains.Length > 0)
            {
                for (; i < craft.RemainSlotIndies.Length; i++)
                {
                    if (!machine.AquireItems(craft.RemainSlotIndies[i], Remains[i], RemainCounts[i])) return false;
                }
            }
            //结果位的燃料是否和配方一致
            if (FuelResults.Length > 0)
            {
                for (i = 0; i < craft.ResultSlotIndies.Length; i++)
                {
                    if (!machine.AquireFuel(craft.ResultSlotIndies[i], FuelResults[i], FuelAmountResults[i])) return false;
                }
            }

            //检查燃料位是否一致
            if (fuelIngredians.Length > 0)
            {
                for (i = 0; i < FuelCraftChecks.Length; i++)
                {
                    if (FuelCraftChecks[i])
                    {
                        var a = m_fuelIngredians[i];
                        var b = fuelIngredians[i];
                        if (m_fuelIngredianAmount[i] < fuelIngrediansAmount[i]) return false;
                        if (a == null) a = string.Empty;
                        if (b == null) b = string.Empty;
                        if (a != b) return false;
                    }
                }
            }
            if (fuelIngredianTypes.Length > 0)
            {
                for (i = 0; i < FuelCraftChecks.Length; i++)
                {
                    if (FuelCraftChecks[i])
                    {
                        var a = m_fuelIngredianTypes[i];
                        var b = fuelIngredianTypes[i];
                        if (a != b) return false;
                    }
                }
            }

            //检查物品位是否一致
            if (ingredians.Length > 0)
            {
                for (i = 0; i < CraftChecks.Length; i++)
                {
                    if (CraftChecks[i])
                    {
                        var a = m_ingredians[i];
                        var b = ingredians[i];
                        if (a == null) a = string.Empty;
                        if (b == null) b = string.Empty;
                        if (a != b) return false;
                    }
                }
            }
            //检查热能等级是否一致
            if (heatLevel < requireHeatLevel)
            {
                player?.ComponentGui.DisplaySmallMessage($"热能等级不够，需要：{requireHeatLevel},当前：{heatLevel}",Color.White,false,true);
                return false;
            }
            //检查玩家等级是否一致
            if (player != null && player.PlayerData.Level < requirePlayerLevel)
            {
                player?.ComponentGui.DisplaySmallMessage($"你需要等级{requirePlayerLevel}才能制作", Color.White, false, true);
                return false;
            }
            else if (requirePlayerLevel > 1) return false;

            return true;
        }

        /// <summary>
        /// 变换摆谱从0,0开始
        /// </summary>
        /// <param name="inventory">箱子</param>
        /// <param name="size">合成配方大小，如3x3</param>
        /// <param name="Flip">是否翻转配方</param>
        /// <param name="result">重新摆谱后的Index索引</param>
        public static int[] TransformRecipe(string[] ingredians, Point2 size, bool Flip = false)
        {
            int max = size.X * size.Y;
            int[] transformedIngredian = new int[max];
            Point2 point = size;
            for (int i = 0; i < size.Y; i++)
            {//y
                for (int j = 0; j < size.X; j++)
                {//x
                    int k = j + i * size.X;
                    if (k < ingredians.Length)
                    {
                        if (!string.IsNullOrEmpty(ingredians[k]))
                        {
                            point.X = MathUtils.Min(point.X, j);
                            point.Y = MathUtils.Min(point.Y, i);
                        }
                    }
                    else break;
                }
            }
            int pos = 0;
            int endY = point.Y + size.Y;
            int endX = point.X + size.X;
            for (int i = point.Y; i < endY; i++)
            {
                for (int j = point.X; j < endX; j++)
                {
                    //垂直翻转
                    int p;
                    if (Flip) p = endX - 1 - j + i * size.X;
                    else p = j + i * size.X;
                    if (p < ingredians.Length && p < max)
                    {
                        transformedIngredian[pos++] = p;
                    }
                    else
                    {
                        transformedIngredian[pos++] = -1;
                    }
                }
            }
            return transformedIngredian;
        }

        /// <summary>
        /// 普通能量机器合成
        /// </summary>
        /// <param name="machine"></param>
        /// <param name="ControlTimeRatio"></param>
        public static void CircleCraft(ComponentEnergyMachine machine, float ControlTimeRatio = 1f)
        {
            var craftDevice = machine.CraftDevice;

            var ctaftTable = machine as Interface.IMekCraftableMachine;

            if (ctaftTable.CurrentRecipe != null)
            {
                bool allowCraft = true;
                //有电且够用
                if (ctaftTable.CraftPowerUse > 0 && machine.Power - ctaftTable.CraftPowerUse < 0)
                {
                    allowCraft = false;
                }
                if (allowCraft)
                {
                    if (ctaftTable.CraftProgress < 1f)
                    {
                        ctaftTable.CraftProgress = MathUtils.Min(ctaftTable.CraftProgress + 0.15f * Time.FrameDuration * ControlTimeRatio, 1f);
                        machine.IsCrafting = true;
                    }
                    else
                    {
                        //清除合成格子燃料
                        if (ctaftTable.CurrentRecipe.fuelIngredians.Length > 0)
                        {
                            for (int i = 0; i < craftDevice.FuelCraftSlotIndies.Length; i++)
                            {
                                if (i < ctaftTable.CurrentRecipe.FuelCraftChecks.Length && ctaftTable.CurrentRecipe.FuelCraftChecks[i])
                                {
                                    var slotIndex = craftDevice.FuelCraftSlotIndies[i];
                                    var slot = machine.Slots[slotIndex];
                                    slot.FuelAmount -= ctaftTable.CurrentRecipe.fuelIngrediansAmount[i];
                                }
                            }
                        }
                        //清除合成格子物品
                        if (ctaftTable.CurrentRecipe.ingredians.Length > 0)
                        {
                            for (int i = 0; i < craftDevice.CraftSlotIndies.Length; i++)
                            {
                                var slotIndex = craftDevice.CraftSlotIndies[i];
                                var slot = machine.Slots[slotIndex];
                                if (i < ctaftTable.CurrentRecipe.CraftChecks.Length && slot.Count > 0)
                                {
                                    if (ctaftTable.CurrentRecipe.CraftChecks[i])
                                    {
                                        var block = BlocksManager.Blocks[Terrain.ExtractContents(slot.Value)];
                                        if (block is MekBlock mek)
                                        {
                                            int v = mek.GetCraftedRemainValue(slot.Value);
                                            if (v == 0) slot.Count -= 1;
                                            else slot.Value = v;
                                        }
                                        else slot.Count -= 1;
                                    }
                                }
                            }
                        }
                        //添加合成结果物品
                        if (ctaftTable.CurrentRecipe.Results.Length > 0)
                        {
                            for (int i = 0; i < craftDevice.ResultSlotIndies.Length; i++)
                            {
                                var slot = machine.Slots[craftDevice.ResultSlotIndies[i]];
                                var block = BlocksManager.Blocks[Terrain.ExtractContents(slot.Value)];
                                int v = ctaftTable.CurrentRecipe.Results[i];
                                if (block is MekBlock mek)
                                {
                                    slot.Value = mek.GetCraftedResultValue(v);
                                }
                                else
                                {
                                    slot.Value = v;
                                }
                                slot.Count += ctaftTable.CurrentRecipe.ResultCounts[i];
                            }
                        }
                        if (ctaftTable.CurrentRecipe.FuelResults.Length > 0)
                        {
                            for (int i = 0; i < craftDevice.ResultSlotIndies.Length; i++)
                            {
                                var slot = machine.Slots[craftDevice.ResultSlotIndies[i]];
                                slot.FuelValue = ctaftTable.CurrentRecipe.FuelResults[i];
                                slot.FuelType = ctaftTable.CurrentRecipe.FuelResultTypes[i];
                                slot.FuelAmount += ctaftTable.CurrentRecipe.FuelAmountResults[i];
                            }
                        }
                        if (ctaftTable.CurrentRecipe.Remains.Length > 0)
                        {
                            for (int i = 0; i < craftDevice.RemainSlotIndies.Length; i++)
                            {
                                var slot = machine.Slots[craftDevice.RemainSlotIndies[i]];
                                var v = ctaftTable.CurrentRecipe.Remains[i];
                                var block = BlocksManager.Blocks[Terrain.ExtractContents(v)];
                                if (block is MekBlock mek)
                                {
                                    slot.Value = mek.GetCraftedResultValue(v);
                                }
                                else
                                {
                                    slot.Value = v;
                                }
                                slot.Count += ctaftTable.CurrentRecipe.RemainCounts[i];
                            }
                        }
                        ctaftTable.CraftProgress = 0f;
                        machine.OnSlotChange();
                    }
                    machine.Power -= ctaftTable.CraftPowerUse;
                }else machine.IsCrafting = false;
            }
            else
            {
                if (Time.PeriodicEvent(1.0, 0.0)) machine.OnSlotChange();
                //进度衰退
                if (ctaftTable.CraftProgress > 0) ctaftTable.CraftProgress = MathUtils.Max(ctaftTable.CraftProgress - 0.15f * Time.FrameDuration * ControlTimeRatio, 0f);
                machine.IsCrafting = false;
            }
        }


    }
}
